home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / calc202a.lha / calc-2.02a / calc-bin.el < prev    next >
Lisp/Scheme  |  1993-06-01  |  25KB  |  848 lines

  1. ;; Calculator for GNU Emacs, part II [calc-bin.el]
  2. ;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  3. ;; Written by Dave Gillespie, daveg@synaptics.com.
  4.  
  5. ;; This file is part of GNU Emacs.
  6.  
  7. ;; GNU Emacs is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  9. ;; accepts responsibility to anyone for the consequences of using it
  10. ;; or for whether it serves any particular purpose or works at all,
  11. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  12. ;; License for full details.
  13.  
  14. ;; Everyone is granted permission to copy, modify and redistribute
  15. ;; GNU Emacs, but only under the conditions described in the
  16. ;; GNU Emacs General Public License.   A copy of this license is
  17. ;; supposed to have been given to you along with GNU Emacs so you
  18. ;; can know your rights and responsibilities.  It should be in a
  19. ;; file named COPYING.  Among other things, the copyright notice
  20. ;; and this notice must be preserved on all copies.
  21.  
  22.  
  23.  
  24. ;; This file is autoloaded from calc-ext.el.
  25. (require 'calc-ext)
  26.  
  27. (require 'calc-macs)
  28.  
  29. (defun calc-Need-calc-bin () nil)
  30.  
  31.  
  32. ;;; b-prefix binary commands.
  33.  
  34. (defun calc-and (n)
  35.   (interactive "P")
  36.   (calc-slow-wrapper
  37.    (calc-enter-result 2 "and"
  38.               (append '(calcFunc-and)
  39.                   (calc-top-list-n 2)
  40.                   (and n (list (prefix-numeric-value n))))))
  41. )
  42.  
  43. (defun calc-or (n)
  44.   (interactive "P")
  45.   (calc-slow-wrapper
  46.    (calc-enter-result 2 "or"
  47.               (append '(calcFunc-or)
  48.                   (calc-top-list-n 2)
  49.                   (and n (list (prefix-numeric-value n))))))
  50. )
  51.  
  52. (defun calc-xor (n)
  53.   (interactive "P")
  54.   (calc-slow-wrapper
  55.    (calc-enter-result 2 "xor"
  56.               (append '(calcFunc-xor)
  57.                   (calc-top-list-n 2)
  58.                   (and n (list (prefix-numeric-value n))))))
  59. )
  60.  
  61. (defun calc-diff (n)
  62.   (interactive "P")
  63.   (calc-slow-wrapper
  64.    (calc-enter-result 2 "diff"
  65.               (append '(calcFunc-diff)
  66.                   (calc-top-list-n 2)
  67.                   (and n (list (prefix-numeric-value n))))))
  68. )
  69.  
  70. (defun calc-not (n)
  71.   (interactive "P")
  72.   (calc-slow-wrapper
  73.    (calc-enter-result 1 "not"
  74.               (append '(calcFunc-not)
  75.                   (calc-top-list-n 1)
  76.                   (and n (list (prefix-numeric-value n))))))
  77. )
  78.  
  79. (defun calc-lshift-binary (n)
  80.   (interactive "P")
  81.   (calc-slow-wrapper
  82.    (let ((hyp (if (calc-is-hyperbolic) 2 1)))
  83.      (calc-enter-result hyp "lsh"
  84.             (append '(calcFunc-lsh)
  85.                 (calc-top-list-n hyp)
  86.                 (and n (list (prefix-numeric-value n)))))))
  87. )
  88.  
  89. (defun calc-rshift-binary (n)
  90.   (interactive "P")
  91.   (calc-slow-wrapper
  92.    (let ((hyp (if (calc-is-hyperbolic) 2 1)))
  93.      (calc-enter-result hyp "rsh"
  94.             (append '(calcFunc-rsh)
  95.                 (calc-top-list-n hyp)
  96.                 (and n (list (prefix-numeric-value n)))))))
  97. )
  98.  
  99. (defun calc-lshift-arith (n)
  100.   (interactive "P")
  101.   (calc-slow-wrapper
  102.    (let ((hyp (if (calc-is-hyperbolic) 2 1)))
  103.      (calc-enter-result hyp "ash"
  104.             (append '(calcFunc-ash)
  105.                 (calc-top-list-n hyp)
  106.                 (and n (list (prefix-numeric-value n)))))))
  107. )
  108.  
  109. (defun calc-rshift-arith (n)
  110.   (interactive "P")
  111.   (calc-slow-wrapper
  112.    (let ((hyp (if (calc-is-hyperbolic) 2 1)))
  113.      (calc-enter-result hyp "rash"
  114.             (append '(calcFunc-rash)
  115.                 (calc-top-list-n hyp)
  116.                 (and n (list (prefix-numeric-value n)))))))
  117. )
  118.  
  119. (defun calc-rotate-binary (n)
  120.   (interactive "P")
  121.   (calc-slow-wrapper
  122.    (let ((hyp (if (calc-is-hyperbolic) 2 1)))
  123.      (calc-enter-result hyp "rot"
  124.             (append '(calcFunc-rot)
  125.                 (calc-top-list-n hyp)
  126.                 (and n (list (prefix-numeric-value n)))))))
  127. )
  128.  
  129. (defun calc-clip (n)
  130.   (interactive "P")
  131.   (calc-slow-wrapper
  132.    (calc-enter-result 1 "clip"
  133.               (append '(calcFunc-clip)
  134.                   (calc-top-list-n 1)
  135.                   (and n (list (prefix-numeric-value n))))))
  136. )
  137.  
  138. (defun calc-word-size (n)
  139.   (interactive "P")
  140.   (calc-wrapper
  141.    (or n (setq n (read-string (format "Binary word size: (default %d) "
  142.                       calc-word-size))))
  143.    (setq n (if (stringp n)
  144.            (if (equal n "")
  145.            calc-word-size
  146.          (if (string-match "\\`[-+]?[0-9]+\\'" n)
  147.              (string-to-int n)
  148.            (error "Expected an integer")))
  149.          (prefix-numeric-value n)))
  150.    (or (= n calc-word-size)
  151.        (if (> (math-abs n) 100)
  152.        (calc-change-mode 'calc-word-size n calc-leading-zeros)
  153.      (calc-change-mode '(calc-word-size calc-previous-modulo)
  154.                (list n (math-power-of-2 (math-abs n)))
  155.                calc-leading-zeros)))
  156.    (if (< n 0)
  157.        (message "Binary word size is %d bits (2's complement)." (- n))
  158.      (message "Binary word size is %d bits." n)))
  159. )
  160.  
  161.  
  162.  
  163.  
  164.  
  165. ;;; d-prefix mode commands.
  166.  
  167. (defun calc-radix (n)
  168.   (interactive "NDisplay radix (2-36): ")
  169.   (calc-wrapper
  170.    (if (and (>= n 2) (<= n 36))
  171.        (progn
  172.      (calc-change-mode 'calc-number-radix n t)
  173.      ;; also change global value so minibuffer sees it
  174.      (setq-default calc-number-radix calc-number-radix))
  175.      (setq n calc-number-radix))
  176.    (message "Number radix is %d." n))
  177. )
  178.  
  179. (defun calc-decimal-radix ()
  180.   (interactive)
  181.   (calc-radix 10)
  182. )
  183.  
  184. (defun calc-binary-radix ()
  185.   (interactive)
  186.   (calc-radix 2)
  187. )
  188.  
  189. (defun calc-octal-radix ()
  190.   (interactive)
  191.   (calc-radix 8)
  192. )
  193.  
  194. (defun calc-hex-radix ()
  195.   (interactive)
  196.   (calc-radix 16)
  197. )
  198.  
  199. (defun calc-leading-zeros (n)
  200.   (interactive "P")
  201.   (calc-wrapper
  202.    (if (calc-change-mode 'calc-leading-zeros n t t)
  203.        (message "Zero-padding integers to %d digits (assuming radix %d)."
  204.         (let* ((calc-internal-prec 6))
  205.           (math-compute-max-digits (math-abs calc-word-size)
  206.                        calc-number-radix))
  207.         calc-number-radix)
  208.      (message "Omitting leading zeros on integers.")))
  209. )
  210.  
  211.  
  212. (defvar math-power-of-2-cache (list 1 2 4 8 16 32 64 128 256 512 1024))
  213. (defvar math-big-power-of-2-cache nil)
  214. (defun math-power-of-2 (n)    ;  [I I] [Public]
  215.   (if (and (natnump n) (<= n 100))
  216.       (or (nth n math-power-of-2-cache)
  217.       (let* ((i (length math-power-of-2-cache))
  218.          (val (nth (1- i) math-power-of-2-cache)))
  219.         (while (<= i n)
  220.           (setq val (math-mul val 2)
  221.             math-power-of-2-cache (nconc math-power-of-2-cache
  222.                          (list val))
  223.             i (1+ i)))
  224.         val))
  225.     (let ((found (assq n math-big-power-of-2-cache)))
  226.       (if found
  227.       (cdr found)
  228.     (let ((po2 (math-ipow 2 n)))
  229.       (setq math-big-power-of-2-cache
  230.         (cons (cons n po2) math-big-power-of-2-cache))
  231.       po2))))
  232. )
  233.  
  234. (defun math-integer-log2 (n)    ; [I I] [Public]
  235.   (let ((i 0)
  236.     (p math-power-of-2-cache)
  237.     val)
  238.     (while (and p (Math-natnum-lessp (setq val (car p)) n))
  239.       (setq p (cdr p)
  240.         i (1+ i)))
  241.     (if p
  242.     (and (equal val n)
  243.          i)
  244.       (while (Math-natnum-lessp
  245.           (prog1
  246.           (setq val (math-mul val 2))
  247.         (setq math-power-of-2-cache (nconc math-power-of-2-cache
  248.                            (list val))))
  249.           n)
  250.     (setq i (1+ i)))
  251.       (and (equal val n)
  252.        i)))
  253. )
  254.  
  255.  
  256.  
  257.  
  258. ;;; Bitwise operations.
  259.  
  260. (defun calcFunc-and (a b &optional w)   ; [I I I] [Public]
  261.   (cond ((Math-messy-integerp w)
  262.      (calcFunc-and a b (math-trunc w)))
  263.     ((and w (not (integerp w)))
  264.      (math-reject-arg w 'fixnump))
  265.     ((and (integerp a) (integerp b))
  266.      (math-clip (logand a b) w))
  267.     ((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod))
  268.      (math-binary-modulo-args 'calcFunc-and a b w))
  269.     ((not (Math-num-integerp a))
  270.      (math-reject-arg a 'integerp))
  271.     ((not (Math-num-integerp b))
  272.      (math-reject-arg b 'integerp))
  273.     (t (math-clip (cons 'bigpos
  274.                 (math-and-bignum (math-binary-arg a w)
  275.                          (math-binary-arg b w)))
  276.               w)))
  277. )
  278.  
  279. (defun math-binary-arg (a w)
  280.   (if (not (Math-integerp a))
  281.       (setq a (math-trunc a)))
  282.   (if (Math-integer-negp a)
  283.       (math-not-bignum (cdr (math-bignum-test (math-sub -1 a)))
  284.                (math-abs (if w (math-trunc w) calc-word-size)))
  285.     (cdr (Math-bignum-test a)))
  286. )
  287.  
  288. (defun math-binary-modulo-args (f a b w)
  289.   (let (mod)
  290.     (if (eq (car-safe a) 'mod)
  291.     (progn
  292.       (setq mod (nth 2 a)
  293.         a (nth 1 a))
  294.       (if (eq (car-safe b) 'mod)
  295.           (if (equal mod (nth 2 b))
  296.           (setq b (nth 1 b))
  297.         (math-reject-arg b "*Inconsistent modulos"))))
  298.       (setq mod (nth 2 b)
  299.         b (nth 1 b)))
  300.     (if (Math-messy-integerp mod)
  301.     (setq mod (math-trunc mod))
  302.       (or (Math-integerp mod)
  303.       (math-reject-arg mod 'integerp)))
  304.     (let ((bits (math-integer-log2 mod)))
  305.       (if bits
  306.       (if w
  307.           (if (/= w bits)
  308.           (calc-record-why
  309.            "*Warning: Modulo inconsistent with word size"))
  310.         (setq w bits))
  311.     (calc-record-why "*Warning: Modulo is not a power of 2"))
  312.       (math-make-mod (if b
  313.              (funcall f a b w)
  314.                (funcall f a w))
  315.              mod)))
  316. )
  317.  
  318. (defun math-and-bignum (a b)   ; [l l l]
  319.   (and a b
  320.        (let ((qa (math-div-bignum-digit a 512))
  321.          (qb (math-div-bignum-digit b 512)))
  322.      (math-mul-bignum-digit (math-and-bignum (math-norm-bignum (car qa))
  323.                           (math-norm-bignum (car qb)))
  324.                  512
  325.                  (logand (cdr qa) (cdr qb)))))
  326. )
  327.  
  328. (defun calcFunc-or (a b &optional w)   ; [I I I] [Public]
  329.   (cond ((Math-messy-integerp w)
  330.      (calcFunc-or a b (math-trunc w)))
  331.     ((and w (not (integerp w)))
  332.      (math-reject-arg w 'fixnump))
  333.     ((and (integerp a) (integerp b))
  334.      (math-clip (logior a b) w))
  335.     ((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod))
  336.      (math-binary-modulo-args 'calcFunc-or a b w))
  337.     ((not (Math-num-integerp a))
  338.      (math-reject-arg a 'integerp))
  339.     ((not (Math-num-integerp b))
  340.      (math-reject-arg b 'integerp))
  341.     (t (math-clip (cons 'bigpos
  342.                 (math-or-bignum (math-binary-arg a w)
  343.                         (math-binary-arg b w)))
  344.               w)))
  345. )
  346.  
  347. (defun math-or-bignum (a b)   ; [l l l]
  348.   (and (or a b)
  349.        (let ((qa (math-div-bignum-digit a 512))
  350.          (qb (math-div-bignum-digit b 512)))
  351.      (math-mul-bignum-digit (math-or-bignum (math-norm-bignum (car qa))
  352.                          (math-norm-bignum (car qb)))
  353.                  512
  354.                  (logior (cdr qa) (cdr qb)))))
  355. )
  356.  
  357. (defun calcFunc-xor (a b &optional w)   ; [I I I] [Public]
  358.   (cond ((Math-messy-integerp w)
  359.      (calcFunc-xor a b (math-trunc w)))
  360.     ((and w (not (integerp w)))
  361.      (math-reject-arg w 'fixnump))
  362.     ((and (integerp a) (integerp b))
  363.      (math-clip (logxor a b) w))
  364.     ((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod))
  365.      (math-binary-modulo-args 'calcFunc-xor a b w))
  366.     ((not (Math-num-integerp a))
  367.      (math-reject-arg a 'integerp))
  368.     ((not (Math-num-integerp b))
  369.      (math-reject-arg b 'integerp))
  370.     (t (math-clip (cons 'bigpos
  371.                 (math-xor-bignum (math-binary-arg a w)
  372.                          (math-binary-arg b w)))
  373.               w)))
  374. )
  375.  
  376. (defun math-xor-bignum (a b)   ; [l l l]
  377.   (and (or a b)
  378.        (let ((qa (math-div-bignum-digit a 512))
  379.          (qb (math-div-bignum-digit b 512)))
  380.      (math-mul-bignum-digit (math-xor-bignum (math-norm-bignum (car qa))
  381.                           (math-norm-bignum (car qb)))
  382.                  512
  383.                  (logxor (cdr qa) (cdr qb)))))
  384. )
  385.  
  386. (defun calcFunc-diff (a b &optional w)   ; [I I I] [Public]
  387.   (cond ((Math-messy-integerp w)
  388.      (calcFunc-diff a b (math-trunc w)))
  389.     ((and w (not (integerp w)))
  390.      (math-reject-arg w 'fixnump))
  391.     ((and (integerp a) (integerp b))
  392.      (math-clip (logand a (lognot b)) w))
  393.     ((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod))
  394.      (math-binary-modulo-args 'calcFunc-diff a b w))
  395.     ((not (Math-num-integerp a))
  396.      (math-reject-arg a 'integerp))
  397.     ((not (Math-num-integerp b))
  398.      (math-reject-arg b 'integerp))
  399.     (t (math-clip (cons 'bigpos
  400.                 (math-diff-bignum (math-binary-arg a w)
  401.                           (math-binary-arg b w)))
  402.               w)))
  403. )
  404.  
  405. (defun math-diff-bignum (a b)   ; [l l l]
  406.   (and a
  407.        (let ((qa (math-div-bignum-digit a 512))
  408.          (qb (math-div-bignum-digit b 512)))
  409.      (math-mul-bignum-digit (math-diff-bignum (math-norm-bignum (car qa))
  410.                            (math-norm-bignum (car qb)))
  411.                  512
  412.                  (logand (cdr qa) (lognot (cdr qb))))))
  413. )
  414.  
  415. (defun calcFunc-not (a &optional w)   ; [I I] [Public]
  416.   (cond ((Math-messy-integerp w)
  417.      (calcFunc-not a (math-trunc w)))
  418.     ((eq (car-safe a) 'mod)
  419.      (math-binary-modulo-args 'calcFunc-not a nil w))
  420.     ((and w (not (integerp w)))
  421.      (math-reject-arg w 'fixnump))
  422.     ((not (Math-num-integerp a))
  423.      (math-reject-arg a 'integerp))
  424.     ((< (or w (setq w calc-word-size)) 0)
  425.      (math-clip (calcFunc-not a (- w)) w))
  426.     (t (math-normalize
  427.         (cons 'bigpos
  428.           (math-not-bignum (math-binary-arg a w)
  429.                    w)))))
  430. )
  431.  
  432. (defun math-not-bignum (a w)   ; [l l]
  433.   (let ((q (math-div-bignum-digit a 512)))
  434.     (if (<= w 9)
  435.     (list (logand (lognot (cdr q))
  436.               (1- (lsh 1 w))))
  437.       (math-mul-bignum-digit (math-not-bignum (math-norm-bignum (car q))
  438.                            (- w 9))
  439.                   512
  440.                   (logxor (cdr q) 511))))
  441. )
  442.  
  443. (defun calcFunc-lsh (a &optional n w)   ; [I I] [Public]
  444.   (setq a (math-trunc a)
  445.     n (if n (math-trunc n) 1))
  446.   (if (eq (car-safe a) 'mod)
  447.       (math-binary-modulo-args 'calcFunc-lsh a n w)
  448.     (setq w (if w (math-trunc w) calc-word-size))
  449.     (or (integerp w)
  450.     (math-reject-arg w 'fixnump))
  451.     (or (Math-integerp a)
  452.     (math-reject-arg a 'integerp))
  453.     (or (Math-integerp n)
  454.     (math-reject-arg n 'integerp))
  455.     (if (< w 0)
  456.     (math-clip (calcFunc-lsh a n (- w)) w)
  457.       (if (Math-integer-negp a)
  458.       (setq a (math-clip a w)))
  459.       (cond ((or (Math-lessp n (- w))
  460.          (Math-lessp w n))
  461.          0)
  462.         ((< n 0)
  463.          (math-quotient (math-clip a w) (math-power-of-2 (- n))))
  464.         (t
  465.          (math-clip (math-mul a (math-power-of-2 n)) w)))))
  466. )
  467.  
  468. (defun calcFunc-rsh (a &optional n w)   ; [I I] [Public]
  469.   (calcFunc-lsh a (math-neg (or n 1)) w)
  470. )
  471.  
  472. (defun calcFunc-ash (a &optional n w)   ; [I I] [Public]
  473.   (if (or (null n)
  474.       (not (Math-negp n)))
  475.       (calcFunc-lsh a n w)
  476.     (setq a (math-trunc a)
  477.       n (if n (math-trunc n) 1))
  478.     (if (eq (car-safe a) 'mod)
  479.     (math-binary-modulo-args 'calcFunc-ash a n w)
  480.       (setq w (if w (math-trunc w) calc-word-size))
  481.       (or (integerp w)
  482.       (math-reject-arg w 'fixnump))
  483.       (or (Math-integerp a)
  484.       (math-reject-arg a 'integerp))
  485.       (or (Math-integerp n)
  486.       (math-reject-arg n 'integerp))
  487.       (if (< w 0)
  488.       (math-clip (calcFunc-ash a n (- w)) w)
  489.     (if (Math-integer-negp a)
  490.         (setq a (math-clip a w)))
  491.     (let ((two-to-sizem1 (math-power-of-2 (1- w)))
  492.           (sh (calcFunc-lsh a n w)))
  493.       (cond ((Math-natnum-lessp a two-to-sizem1)
  494.          sh)
  495.         ((Math-lessp n (- 1 w))
  496.          (math-add (math-mul two-to-sizem1 2) -1))
  497.         (t (let ((two-to-n (math-power-of-2 (- n))))
  498.              (math-add (calcFunc-lsh (math-add two-to-n -1)
  499.                          (+ w n) w)
  500.                    sh))))))))
  501. )
  502.  
  503. (defun calcFunc-rash (a &optional n w)   ; [I I] [Public]
  504.   (calcFunc-ash a (math-neg (or n 1)) w)
  505. )
  506.  
  507. (defun calcFunc-rot (a &optional n w)   ; [I I] [Public]
  508.   (setq a (math-trunc a)
  509.     n (if n (math-trunc n) 1))
  510.   (if (eq (car-safe a) 'mod)
  511.       (math-binary-modulo-args 'calcFunc-rot a n w)
  512.     (setq w (if w (math-trunc w) calc-word-size))
  513.     (or (integerp w)
  514.     (math-reject-arg w 'fixnump))
  515.     (or (Math-integerp a)
  516.     (math-reject-arg a 'integerp))
  517.     (or (Math-integerp n)
  518.     (math-reject-arg n 'integerp))
  519.     (if (< w 0)
  520.     (math-clip (calcFunc-rot a n (- w)) w)
  521.       (if (Math-integer-negp a)
  522.       (setq a (math-clip a w)))
  523.       (cond ((or (Math-integer-negp n)
  524.          (not (Math-natnum-lessp n w)))
  525.          (calcFunc-rot a (math-mod n w) w))
  526.         (t
  527.          (math-add (calcFunc-lsh a (- n w) w)
  528.                (calcFunc-lsh a n w))))))
  529. )
  530.  
  531. (defun math-clip (a &optional w)   ; [I I] [Public]
  532.   (cond ((Math-messy-integerp w)
  533.      (math-clip a (math-trunc w)))
  534.     ((eq (car-safe a) 'mod)
  535.      (math-binary-modulo-args 'math-clip a nil w))
  536.     ((and w (not (integerp w)))
  537.      (math-reject-arg w 'fixnump))
  538.     ((not (Math-num-integerp a))
  539.      (math-reject-arg a 'integerp))
  540.     ((< (or w (setq w calc-word-size)) 0)
  541.      (setq a (math-clip a (- w)))
  542.      (if (Math-natnum-lessp a (math-power-of-2 (- -1 w)))
  543.          a
  544.        (math-sub a (math-power-of-2 (- w)))))
  545.     ((Math-negp a)
  546.      (math-normalize (cons 'bigpos (math-binary-arg a w))))
  547.     ((and (integerp a) (< a 1000000))
  548.      (if (>= w 20)
  549.          a
  550.        (logand a (1- (lsh 1 w)))))
  551.     (t
  552.      (math-normalize
  553.       (cons 'bigpos
  554.         (math-clip-bignum (cdr (math-bignum-test (math-trunc a)))
  555.                   w)))))
  556. )
  557. (fset 'calcFunc-clip (symbol-function 'math-clip))
  558.  
  559. (defun math-clip-bignum (a w)   ; [l l]
  560.   (let ((q (math-div-bignum-digit a 512)))
  561.     (if (<= w 9)
  562.     (list (logand (cdr q)
  563.               (1- (lsh 1 w))))
  564.       (math-mul-bignum-digit (math-clip-bignum (math-norm-bignum (car q))
  565.                         (- w 9))
  566.                   512
  567.                   (cdr q))))
  568. )
  569.  
  570.  
  571.  
  572.  
  573. (defvar math-max-digits-cache nil)
  574. (defun math-compute-max-digits (w r)
  575.   (let* ((pair (+ (* r 100000) w))
  576.      (res (assq pair math-max-digits-cache)))
  577.     (if res
  578.     (cdr res)
  579.       (let* ((calc-command-flags nil)
  580.          (digs (math-ceiling (math-div w (math-real-log2 r)))))
  581.     (setq math-max-digits-cache (cons (cons pair digs)
  582.                       math-max-digits-cache))
  583.     digs)))
  584. )
  585.  
  586. (defvar math-log2-cache (list '(2 . 1)
  587.                   '(4 . 2)
  588.                   '(8 . 3)
  589.                   '(10 . (float 332193 -5))
  590.                   '(16 . 4)
  591.                   '(32 . 5)))
  592. (defun math-real-log2 (x)   ;;; calc-internal-prec must be 6
  593.   (let ((res (assq x math-log2-cache)))
  594.     (if res
  595.     (cdr res)
  596.       (let* ((calc-symbolic-mode nil)
  597.          (calc-display-working-message nil)
  598.          (log (calcFunc-log x 2)))
  599.     (setq math-log2-cache (cons (cons x log) math-log2-cache))
  600.     log)))
  601. )
  602.  
  603. (defconst math-radix-digits ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
  604.                  "A" "B" "C" "D" "E" "F" "G" "H" "I" "J"
  605.                  "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T"
  606.                  "U" "V" "W" "X" "Y" "Z"])
  607.  
  608. (defun math-format-radix (a)   ; [X S]
  609.   (if (< a calc-number-radix)
  610.       (if (< a 0)
  611.       (concat "-" (math-format-radix (- a)))
  612.     (math-format-radix-digit a))
  613.     (let ((s ""))
  614.       (while (> a 0)
  615.     (setq s (concat (math-format-radix-digit (% a calc-number-radix)) s)
  616.           a (/ a calc-number-radix)))
  617.       s))
  618. )
  619.  
  620. (defconst math-binary-digits ["000" "001" "010" "011"
  621.                   "100" "101" "110" "111"])
  622. (defun math-format-binary (a)   ; [X S]
  623.   (if (< a 8)
  624.       (if (< a 0)
  625.       (concat "-" (math-format-binary (- a)))
  626.     (math-format-radix a))
  627.     (let ((s ""))
  628.       (while (> a 7)
  629.     (setq s (concat (aref math-binary-digits (% a 8)) s)
  630.           a (/ a 8)))
  631.       (concat (math-format-radix a) s)))
  632. )
  633.  
  634. (defun math-format-bignum-radix (a)   ; [X L]
  635.   (cond ((null a) "0")
  636.     ((and (null (cdr a))
  637.           (< (car a) calc-number-radix))
  638.      (math-format-radix-digit (car a)))
  639.     (t
  640.      (let ((q (math-div-bignum-digit a calc-number-radix)))
  641.        (concat (math-format-bignum-radix (math-norm-bignum (car q)))
  642.            (math-format-radix-digit (cdr q))))))
  643. )
  644.  
  645. (defun math-format-bignum-binary (a)   ; [X L]
  646.   (cond ((null a) "0")
  647.     ((null (cdr a))
  648.      (math-format-binary (car a)))
  649.     (t
  650.      (let ((q (math-div-bignum-digit a 512)))
  651.        (concat (math-format-bignum-binary (math-norm-bignum (car q)))
  652.            (aref math-binary-digits (/ (cdr q) 64))
  653.            (aref math-binary-digits (% (/ (cdr q) 8) 8))
  654.            (aref math-binary-digits (% (cdr q) 8))))))
  655. )
  656.  
  657. (defun math-format-bignum-octal (a)   ; [X L]
  658.   (cond ((null a) "0")
  659.     ((null (cdr a))
  660.      (math-format-radix (car a)))
  661.     (t
  662.      (let ((q (math-div-bignum-digit a 512)))
  663.        (concat (math-format-bignum-octal (math-norm-bignum (car q)))
  664.            (math-format-radix-digit (/ (cdr q) 64))
  665.            (math-format-radix-digit (% (/ (cdr q) 8) 8))
  666.            (math-format-radix-digit (% (cdr q) 8))))))
  667. )
  668.  
  669. (defun math-format-bignum-hex (a)   ; [X L]
  670.   (cond ((null a) "0")
  671.     ((null (cdr a))
  672.      (math-format-radix (car a)))
  673.     (t
  674.      (let ((q (math-div-bignum-digit a 256)))
  675.        (concat (math-format-bignum-hex (math-norm-bignum (car q)))
  676.            (math-format-radix-digit (/ (cdr q) 16))
  677.            (math-format-radix-digit (% (cdr q) 16))))))
  678. )
  679.  
  680. ;;; Decompose into integer and fractional parts, without depending
  681. ;;; on calc-internal-prec.
  682. (defun math-float-parts (a need-frac)    ; returns ( int frac fracdigs )
  683.   (if (>= (nth 2 a) 0)
  684.       (list (math-scale-rounding (nth 1 a) (nth 2 a)) '(float 0 0) 0)
  685.     (let* ((d (math-numdigs (nth 1 a)))
  686.        (n (- (nth 2 a))))
  687.       (if need-frac
  688.       (if (>= n d)
  689.           (list 0 a n)
  690.         (let ((qr (math-idivmod (nth 1 a) (math-scale-int 1 n))))
  691.           (list (car qr) (math-make-float (cdr qr) (- n)) n)))
  692.     (list (math-scale-rounding (nth 1 a) (nth 2 a))
  693.           '(float 0 0) 0))))
  694. )
  695.  
  696. (defun math-format-radix-float (a prec)
  697.   (let ((fmt (car calc-float-format))
  698.     (figs (nth 1 calc-float-format))
  699.     (point calc-point-char)
  700.     (str nil))
  701.     (if (eq fmt 'fix)
  702.     (let* ((afigs (math-abs figs))
  703.            (fp (math-float-parts a (> afigs 0)))
  704.            (calc-internal-prec (+ 3 (max (nth 2 fp)
  705.                          (math-convert-radix-digits
  706.                           afigs t))))
  707.            (int (car fp))
  708.            (frac (math-round (math-mul (math-normalize (nth 1 fp))
  709.                        (math-radix-float-power afigs)))))
  710.       (if (not (and (math-zerop frac) (math-zerop int) (< figs 0)))
  711.           (let ((math-radix-explicit-format nil))
  712.         (let ((calc-group-digits nil))
  713.           (setq str (if (> afigs 0) (math-format-number frac) ""))
  714.           (if (< (length str) afigs)
  715.               (setq str (concat (make-string (- afigs (length str)) ?0)
  716.                     str))
  717.             (if (> (length str) afigs)
  718.             (setq str (substring str 1)
  719.                   int (math-add int 1))))
  720.           (setq str (concat (math-format-number int) point str)))
  721.         (if calc-group-digits
  722.             (setq str (math-group-float str))))
  723.         (setq figs 0))))
  724.     (or str
  725.     (let* ((prec calc-internal-prec)
  726.            (afigs (if (> figs 0)
  727.               figs
  728.             (max 1 (+ figs
  729.                   (1- (math-convert-radix-digits
  730.                        (max prec
  731.                         (math-numdigs (nth 1 a)))))))))
  732.            (calc-internal-prec (+ 3 (math-convert-radix-digits afigs t)))
  733.            (explo -1) (vlo (math-radix-float-power explo))
  734.            (exphi 1) (vhi (math-radix-float-power exphi))
  735.            expmid vmid eadj)
  736.       (setq a (math-normalize a))
  737.       (if (Math-zerop a)
  738.           (setq explo 0)
  739.         (if (math-lessp-float '(float 1 0) a)
  740.         (while (not (math-lessp-float a vhi))
  741.           (setq explo exphi vlo vhi
  742.             exphi (math-mul exphi 2)
  743.             vhi (math-radix-float-power exphi)))
  744.           (while (math-lessp-float a vlo)
  745.         (setq exphi explo vhi vlo
  746.               explo (math-mul explo 2)
  747.               vlo (math-radix-float-power explo))))
  748.         (while (not (eq (math-sub exphi explo) 1))
  749.           (setq expmid (math-div2 (math-add explo exphi))
  750.             vmid (math-radix-float-power expmid))
  751.           (if (math-lessp-float a vmid)
  752.           (setq exphi expmid vhi vmid)
  753.         (setq explo expmid vlo vmid)))
  754.         (setq a (math-div-float a vlo)))
  755.       (let* ((sc (math-round (math-mul a (math-radix-float-power
  756.                           (1- afigs)))))
  757.          (math-radix-explicit-format nil))
  758.         (let ((calc-group-digits nil))
  759.           (setq str (math-format-number sc))))
  760.       (if (> (length str) afigs)
  761.           (setq str (substring str 0 -1)
  762.             explo (1+ explo)))
  763.       (if (and (eq fmt 'float)
  764.            (math-lessp explo (+ (if (= figs 0)
  765.                         (1- (math-convert-radix-digits
  766.                          prec))
  767.                       afigs)
  768.                     calc-display-sci-high 1))
  769.            (math-lessp calc-display-sci-low explo))
  770.           (let ((dpos (1+ explo)))
  771.         (cond ((<= dpos 0)
  772.                (setq str (concat "0" point (make-string (- dpos) ?0)
  773.                      str)))
  774.               ((> dpos (length str))
  775.                (setq str (concat str (make-string (- dpos (length str))
  776.                               ?0) point)))
  777.               (t
  778.                (setq str (concat (substring str 0 dpos) point
  779.                      (substring str dpos)))))
  780.         (setq explo nil))
  781.         (setq eadj (if (eq fmt 'eng)
  782.                (min (math-mod explo 3) (length str))
  783.              0)
  784.           str (concat (substring str 0 (1+ eadj)) point
  785.                   (substring str (1+ eadj)))))
  786.       (setq pos (length str))
  787.       (while (eq (aref str (1- pos)) ?0) (setq pos (1- pos)))
  788.       (and explo (eq (aref str (1- pos)) ?.) (setq pos (1- pos)))
  789.       (setq str (substring str 0 pos))
  790.       (if calc-group-digits
  791.           (setq str (math-group-float str)))
  792.       (if explo
  793.           (let ((estr (let ((calc-number-radix 10)
  794.                 (calc-group-digits nil))
  795.                 (setq estr (math-format-number
  796.                     (math-sub explo eadj))))))
  797.         (setq str (if (or (memq calc-language '(math maple))
  798.                   (> calc-number-radix 14))
  799.                   (format "%s*%d.^%s" str calc-number-radix estr)
  800.                 (format "%se%s" str estr)))))))
  801.     str)
  802. )
  803.  
  804. (defun math-convert-radix-digits (n &optional to-dec)
  805.   (let ((key (cons n (cons to-dec calc-number-radix))))
  806.     (or (cdr (assoc key math-radix-digits-cache))
  807.     (let* ((calc-internal-prec 6)
  808.            (log (math-div (math-real-log2 calc-number-radix)
  809.                   '(float 332193 -5))))
  810.       (cdr (car (setq math-radix-digits-cache
  811.               (cons (cons key (math-ceiling (if to-dec
  812.                                 (math-mul n log)
  813.                               (math-div n log))))
  814.                 math-radix-digits-cache)))))))
  815. )
  816. (setq math-radix-digits-cache nil)
  817.  
  818. (defun math-radix-float-power (n)
  819.   (if (eq n 0)
  820.       '(float 1 0)
  821.     (or (and (eq calc-number-radix (car math-radix-float-cache-tag))
  822.          (<= calc-internal-prec (cdr math-radix-float-cache-tag)))
  823.     (setq math-radix-float-cache-tag (cons calc-number-radix
  824.                            calc-internal-prec)
  825.           math-radix-float-cache nil))
  826.     (math-normalize
  827.      (or (cdr (assoc n math-radix-float-cache))
  828.      (cdr (car (setq math-radix-float-cache
  829.              (cons (cons
  830.                 n
  831.                 (let ((calc-internal-prec
  832.                        (cdr math-radix-float-cache-tag)))
  833.                   (if (math-negp n)
  834.                       (math-div-float '(float 1 0)
  835.                               (math-radix-float-power
  836.                                (math-neg n)))
  837.                     (math-mul-float (math-sqr-float
  838.                              (math-radix-float-power
  839.                               (math-div2 n)))
  840.                             (if (math-evenp n)
  841.                             '(float 1 0)
  842.                               (math-float
  843.                                calc-number-radix))))))
  844.                    math-radix-float-cache)))))))
  845. )
  846. (setq math-radix-float-cache-tag nil)
  847.  
  848.